#pragma once

#include <iostream>
#include <functional>
#include <string>

#include "InetAddr.hpp"

#define ListenConnection 0
#define NormalConnection 1

class Connection;
class Reactor;

using handler_t = std::function<void(Connection *conn)>;

class Connection
{
public:
    Connection(int sockfd)
        : _sockfd(sockfd)
    {
    }

    void RegisterHandler(handler_t recver, handler_t sender, handler_t excepter)
    {
        _handler_recver = recver;
        _handler_sender = sender;
        _handler_excepter = excepter;
    }

    void SetEvents(uint32_t event)
    {
        _evnets = event;
    }

    void SetConnectionType(int type)
    {
        _type = type;
    }

    void SetAddr(const InetAddr& addr)
    {
        _addr = addr;
    }

    void SetReactor(Reactor* R)
    {
        _R = R;
    }

    int Sockfd()
    {
        return _sockfd;
    }

    int Type()
    {
        return _type;
    }

    uint32_t Events()
    {
        return _evnets;
    }

    std::string& Inbuffer()
    {
        return _inbuffer;
    }

    std::string& Outbuffer()    // 发送数据时需要对_outbuffer进行操作，所以返回引用
    {
        return _outbuffer;
    }

    void DiscardOutbuffer(int n)
    {
        _outbuffer.erase(0, n);
    }

    void AppendInbuffer(const std::string& in)
    {
        _inbuffer += in;
    }

    void AppendOutbuffer(const std::string& out)
    {
        _outbuffer += out;
    }

    void Close()
    {
        if(_sockfd > 0)
            ::close(_sockfd);
    }

private:
    int _sockfd;
    uint32_t _evnets;      // 用来设置连接需要关系的事件
    std::string _inbuffer; // 设置缓冲区来保存报文，保证报文的连贯性。
    std::string _outbuffer;
    int _type;             // 用来区分普通链接和listen链接，用于给链接注册方法时区分

public:
    handler_t _handler_recver;   // 处理读
    handler_t _handler_sender;   // 处理写
    handler_t _handler_excepter; // 处理异常

    Reactor *_R; // 用于链接调用Reactor的方法，比如说AddConnection()
    InetAddr _addr;
};